/**
 * @file port_adc.c
 * @brief
 * @author lijingjie (lijingjie@pthyidh.com)
 * @date 2024-11-08 02:24:52
 *
 * @copyright Copyright (c) 2024 by 深圳市鹏天微智能科技有限公司, All Rights Reserved.
 */

/* ==================== [Includes] ========================================== */

#include "xf_hal_port.h"

#if XF_HAL_ADC_IS_ENABLE

#include <stdio.h>
#include <stdlib.h>
#include <math.h>

#include "pt3220.h"
#include "drvs.h"

#include "xf_utils.h"
#include "xf_init.h"

/* ==================== [Defines] =========================================== */

#define XF_HAL_ADC_DEFAULT_ENABLE       false
#define XF_HAL_ADC_DEFAULT_RESOLUTION   0 // 支持10bit的分辨率
#define XF_HAL_ADC_DEFAULT_SAMPLE_RATE  1000

#define TAG   ("PORT_ADC")

/* ==================== [Typedefs] ========================================== */

/* ==================== [Static Prototypes] ================================= */

/* ==================== [Static Variables] ================================== */

/* ==================== [Macros] ============================================ */

/* ==================== [Global Functions] ================================== */

/* ==================== [Static Functions] ================================== */

static const int8_t adc_io_to_channel[] = { SADC_CH_AIN0, SADC_CH_AIN1, SADC_CH_AIN2, -1, SADC_CH_AIN3, SADC_CH_AIN4,
                                            SADC_CH_AIN5, SADC_CH_AIN6, SADC_CH_AIN7, SADC_CH_AIN8, SADC_CH_AIN9,
                                            SADC_CH_AIN0, SADC_CH_AIN1, SADC_CH_AIN2, SADC_CH_AIN4, SADC_CH_AIN5, SADC_CH_AIN6,
                                            -1, -1
                                            };

typedef struct _port_adc_t {
    uint8_t channel;
    uint8_t adc_output_pin;
} port_adc_t;

static xf_err_t port_adc_open(xf_hal_dev_t *dev)
{
    port_adc_t *adc = (port_adc_t *)xf_malloc(sizeof(port_adc_t));
    if (adc == NULL) {
        return XF_ERR_NO_MEM;
    }
    memset(adc, 0, sizeof(port_adc_t));

    adc->channel = adc_io_to_channel[dev->id];
    adc->adc_output_pin = dev->id;

    dev->platform_data = adc;
    GPIO_DIR_CLR(BIT(adc->adc_output_pin));
    iom_ctrl(adc->adc_output_pin, IOM_ANALOG);

    return XF_OK;
}

static xf_err_t port_adc_ioctl(xf_hal_dev_t *dev, uint32_t cmd, void *config)
{
    xf_hal_adc_config_t *adc_config = (xf_hal_adc_config_t *)config;

    XF_LOGD(TAG, "cmd:%ld", cmd);
    if (cmd == XF_HAL_ADC_CMD_DEFAULT) {
        adc_config->enable = XF_HAL_ADC_DEFAULT_ENABLE;
        adc_config->resolution = XF_HAL_ADC_DEFAULT_RESOLUTION;
        adc_config->sample_rate = XF_HAL_ADC_DEFAULT_SAMPLE_RATE;

        return XF_OK;
    }

    if (cmd == XF_HAL_ADC_CMD_ALL) {
        return XF_OK;
    }

    if (cmd & XF_HAL_ADC_CMD_ENABLE) {
        if (adc_config->enable) {
            sadc_init(SADC_ANA_VREF_VDD);
        } else  {
            sadc_deinit();
        }
    }

    if (cmd & XF_HAL_ADC_CMD_RESOLUTION && adc_config->enable) {
        // 不支持动态设置参数
        return XF_ERR_NOT_SUPPORTED;
    }

    if (cmd & XF_HAL_ADC_CMD_SAMPLE_RATE && adc_config->enable) {
        // 不支持动态设置参数
        return XF_ERR_NOT_SUPPORTED;
    }

    return XF_OK;
}

static int port_adc_read(xf_hal_dev_t *dev, void *buf, size_t count)
{
    port_adc_t *adc_config = (port_adc_t *)dev->platform_data;
    uint16_t ret = sadc_read(adc_config->channel, 0);
    memcpy(buf, &ret, count);
    return count;
}

static int port_adc_write(xf_hal_dev_t *dev, const void *buf, size_t count)
{
    // no need
    return -XF_ERR_NOT_SUPPORTED;
}

static xf_err_t port_adc_close(xf_hal_dev_t *dev)
{
    port_adc_t *adc_config = (port_adc_t *)dev->platform_data;
    xf_free(adc_config);
    return XF_OK;
}

static int xf_hal_adc_reg(void)
{
    xf_driver_ops_t ops = {
        .open = port_adc_open,
        .ioctl = port_adc_ioctl,
        .write = port_adc_write,
        .read = port_adc_read,
        .close = port_adc_close,
    };
    xf_hal_adc_register(&ops);
    return XF_OK;
}

XF_INIT_EXPORT_PREV(xf_hal_adc_reg);

#endif

